pub(crate) mod _utils;
mod aggregator;
mod answer_statement;
mod classifier_statement;
mod cli;
mod data;
mod extractor;
mod generator;
mod http;
mod knowledge_statement;
mod list;
mod llm;
mod meta;
mod model;
mod prompt;
mod pubsub;
mod script;
mod template_statement;
mod tool;
mod wasm;
mod workflow_statement;
use std::sync::{Arc, Mutex};
mod wait;

use model_graph_types::container::workflow::{
    WorkflowBlock, WorkflowBlockBody, WorkflowBlockExecuteResult, WorkflowBlockStatement,
    WorkflowGraphNodeStatement,
};

use crate::workflow::context::WorkflowContext;

pub async fn execute(
    id: &String,
    block: &WorkflowBlockStatement,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<WorkflowBlockExecuteResult> {
    //
    let result = match block {
        WorkflowBlockStatement::Http(v) => http::execute(v, context.clone()).await?,
        WorkflowBlockStatement::Answer(v) => answer_statement::execute(v, context.clone()).await?,
        WorkflowBlockStatement::LLM(v) => llm::execute(v, context.clone()).await?,
        WorkflowBlockStatement::CLI(v) => cli::execute(v, context.clone()).await?,
        WorkflowBlockStatement::Wait(v) => wait::execute(v, context.clone()).await?,
        WorkflowBlockStatement::SpeechGenerator(v) => {
            generator::speech_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::VideoGenerator(v) => {
            generator::video_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::ImageGenerator(v) => {
            generator::image_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::ListOperator(v) => list::execute(v, context.clone()).await?,
        WorkflowBlockStatement::VariableAggregator(v) => {
            aggregator::variable_aggregator_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::MetaOperator(v) => meta::execute(v, context.clone()).await?,
        WorkflowBlockStatement::DataOperator(v) => data::execute(v, context.clone()).await?,
        WorkflowBlockStatement::HtmlExtractor(v) => {
            extractor::html_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::DocumentExtractor(v) => {
            extractor::document_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::Classifier(v) => {
            classifier_statement::execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::Knowledge(v) => {
            knowledge_statement::execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::Prompts(v) => prompt::execute(v, context.clone()).await?,
        WorkflowBlockStatement::PubsubPublish(v) => {
            pubsub::publish_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::PubsubSubscribe(v) => {
            pubsub::subscribe_execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::Script(v) => script::execute(v, context.clone()).await?,
        WorkflowBlockStatement::Template(v) => {
            template_statement::execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::Wasm(v) => wasm::wasm_execute(v, context.clone()).await?,
        WorkflowBlockStatement::SQL(v) => data::sql_execute(v, context.clone()).await?,
        WorkflowBlockStatement::Workflow(v) => {
            workflow_statement::execute(v, context.clone()).await?
        }
        WorkflowBlockStatement::Empty => WorkflowBlockExecuteResult::succeed(),
        _ => WorkflowBlockExecuteResult::succeed(),
    };

    Ok(result)
}

pub async fn compile(
    id: &String,
    node: &WorkflowGraphNodeStatement,
) -> anyhow::Result<WorkflowBlock> {
    let body = match node {
        _ => WorkflowBlockBody::Statement(WorkflowBlockStatement::Empty),
    };
    return Ok(WorkflowBlock::body(body));
}
